/* package org.gridsofts.util */

var org;
if (!org) org = {};
else if (typeof org != "object")
    throw new Error("org already exists and is not an object");

if (!org.gridsofts) org.gridsofts = {};
else if (typeof org.gridsofts != "object")
    throw new Error("org.gridsofts already exists and is not object");

if (!org.gridsofts.util) org.gridsofts.util = {};
else if (typeof org.gridsofts.util != "object")
    throw new Error("org.gridsofts.util already exists and is not object");


/** 判断是否是IE */
org.gridsofts.util.IsIE = true;

if (!window.ActiveXObject) {
    org.gridsofts.util.IsIE = false;
} else {

    org.gridsofts.util.IEVersion = navigator.appVersion.match(/MSIE\s+\d+/i).toString();

    if (org.gridsofts.util.IEVersion != undefined) {
        org.gridsofts.util.IEVersion = org.gridsofts.util.IEVersion.replace(/MSIE\s+/gi, "");
    }
}


/**
 * 类相关工具函数
 * 
 */
org.gridsofts.util.Class = {

    /**
     * 类定义函数
     * 		用于定义一个新类；
     * 		除可以定义类的构造函数、方法、静态变量（方法）之外，还可以实现类的继承、方法借用、接口实现等。
     * 
     * 返回值：新类的构造函数
     * 
     * 参考：O'Reilly (R)《JavaScript权威指南》书中用例
     */
    define: function (data) {
        var classname = data.name;
        var superclass = data.extend || Object;
        var constructor = data.construct || function () { };
        var methods = data.methods || {};
        var statics = data.statics || {};
        var borrows;
        var provides;

        if (!data.borrows) borrows = [];
        else if (data.borrows instanceof Array) borrows = data.borrows;
        else borrows = [data.borrows];

        if (!data.provides) provides = [];
        else if (data.provides instanceof Array) provides = data.provides;
        else provides = [data.provides];

        var proto = new superclass();

        for (var p in proto)
            if (proto.hasOwnProperty(p)) delete proto[p];

        for (var i = 0; i < borrows.length; i++) {
            var c = borrows[i];
            for (var p in c.prototype) {
                if (typeof c.prototype[p] == "function") {
                    proto[p] = c.prototype[p];
                }
            }
        }

        for (var p in methods) proto[p] = methods[p];

        proto.constructor = constructor;
        proto.superclass = superclass;

        if (classname) proto.classname = classname;

        for (var i = 0; i < provides.length; i++) {
            var c = provides[i];
            for (var p in c.prototype) {
                if (typeof c.prototype[p] != "function") continue;
                if (p == "constructor" || p == "superclass") continue;

                if (p in proto && typeof proto[p] == "function"
                    && proto[p].length == c.prototype[p].length) {

                    continue;
                }

                throw new Error("Class " + classname + " does not provides method " + c.classname + "." + p);
            }
        }

        for (var p in statics) constructor[p] = statics[p];

        constructor.prototype = proto;

        return constructor;
    }
};


// --------------------------  以上代码为  定义函数帮助操作，必须放在全部 js 加载脚本之前，需要优先加载

/**
 * 定义全局 变量
 */
var subwayMap;
var zoomScale = {};

/**
 * 路网图类
 */
var Subwaymap = org.gridsofts.util.Class.define({
    name: "Subwaymap",
    /**
     * 类静态属性、方法
     */
    statics: {
        actualWidth: 0,
        actualHeight: 0,

        minWidth: 1000000,
        minHeight: 1000000,

        sequenceZoom: 0.05,  //依次放大、缩小值
        maxZoom: 2,  //最大放大值
        minZoom: 0.2, //最小缩小值

        postionX: 0,
        postionY: 0,

        scale: 0,  //缩放比例

        // 工具集
        utils: {
            obtainPathCoord: function (a) {
                var coord = a + " ";
                for (var i = 1; i < arguments.length - 1; i += 2) {
                    coord += arguments[i] + " " + arguments[i + 1] + " ";
                }
                return coord;
            }
        }
    },

    /**
     * 构造函数
     */
    construct: function (options) {
        if (arguments.length == 0 || typeof (arguments[0]) != "object") {
            throw new Error("Object construct parameter is empty, unable to initialize instance of Subwaymap.");
        }
        // 检查构造参数是否完整
        if (!options.hasOwnProperty("containerId")
            || !options.hasOwnProperty("mapJson")
            || typeof (options["mapJson"]) != "object") {
            throw new Error("The construction parameter lacks the required attributes.");
        }
        // 处理参数
        this.containerId = options["containerId"];
        this.mapJson = options["mapJson"];

        this.type = options["type"];

        // 创建画布
        if (!this.stage) {
            this.stage = new Kinetic.Stage({
                container: this.containerId,
                draggable: true
            });

            this.stage.on('dragend', function (e) {
                if (e.target.nodeType == "Stage") {
                    // 再次执行拖拽画布，重新计算
                    if (Subwaymap.postionX != e.target.attrs.x && Subwaymap.postionY != e.target.attrs.y) {
                        zoomScale.isNewDrag = true;
                    } else {
                        zoomScale.isNewDrag = false;
                    }
                    Subwaymap.postionX = e.target.attrs.x;
                    Subwaymap.postionY = e.target.attrs.y;
                }
            })
        }

        if ("init_load" == this.type) {
            this.repaint();
        }
    },

    methods: {

        /**
         *  更新画布
         */
        updateUI: function () {

            var unscaledWidth = arguments[0] ?? 0;
            var unscaledHeight = arguments[1] ?? 0;

            this.stage.setWidth(unscaledWidth);
            this.stage.setHeight(unscaledHeight);

            Subwaymap.actualWidth += Subwaymap.minWidth;
            Subwaymap.actualHeight += Subwaymap.minHeight;

            var xScale = (this.stage.width()) / Subwaymap.actualWidth;
            var yScale = (this.stage.height() - 20) / Subwaymap.actualHeight;

            //防止初始化页面，缩放比例太大了，导致屏幕装不下
            Subwaymap.scale = xScale < yScale ? xScale : yScale;
            if (Subwaymap.scale > 0.5)
                Subwaymap.scale = 0.5;

            this.stage.scale({ x: Subwaymap.scale, y: Subwaymap.scale });
            this.stage.draw();

            this.moveToCenter();
        },

        /**
         * 画布元素布局居中
         */
        moveToCenter: function () {
            var unscaledWidth = arguments[0] ?? this.stage.getWidth();
            var unscaledHeight = arguments[1] ?? this.stage.getHeight();

            this.stage.setWidth(unscaledWidth);
            this.stage.setHeight(unscaledHeight);

            if (Subwaymap.postionX == 0 && Subwaymap.postionY == 0) {
                Subwaymap.postionX = (this.stage.width() / 2 - Subwaymap.actualWidth * Subwaymap.scale / 2);
                Subwaymap.postionY = (this.stage.height() / 2 - Subwaymap.actualHeight * Subwaymap.scale / 2);
            }
            this.stage.position({ x: Subwaymap.postionX, y: Subwaymap.postionY });

            this.stage.draw();
        },

        initLine: function () {
            // 清空画布
            this.stage.clear();

            // 根据路网图数据，重绘路网线（上行、下行）
            this.paintAllLines(this.stage, this.mapJson);

            //根据路网图数据，重绘路网站点，每条line 会有对应的 station，需要循环遍历
            for (var i = 0; i < this.mapJson.length; i++) {
                this.paintAllStation(this.stage, this.mapJson[i], this.mapJson[i].stopsOnRoute);
            }

            for (var i = 0; i < this.mapJson.length; i++) {
                this.paintAllBusLine(this.stage, this.mapJson[i], this.mapJson[i].stopsOnRoute);
            }
        },
        repaint: function () {
            if (arguments[0] != null && arguments[1] != null) {
                this.mapJson = arguments[0] ?? this.mapJson;
            } else {
                // 清空画布
                this.stage.clear();

                this.initLine();

            }
        },

        /**
         * 绘制所有线路==每条线路一个layer
         */
        paintAllLines: function (stage, lines) {
            if (lines && lines.hasOwnProperty("length") && lines.length > 0) {
                for (var i in lines) {
                    new Subwaymap.LineLayer(stage, lines[i]);
                }
            }
        },

        /**
       * 绘制所有站点和站名===在同一个layer上
       */
        paintAllStation: function (stage, line, stopsOnRoute) {
            if (stopsOnRoute && stopsOnRoute.hasOwnProperty("length") && stopsOnRoute.length > 0) {
                if (this.stationLayer) {
                    this.stationLayer.repaint(line, stopsOnRoute);
                } else {
                    this.stationLayer = new Subwaymap.StationLayer(stage, line, stopsOnRoute);
                }
            }
        },
        paintAllBusLine: function (stage, line, stopsOnRoute) {
            if (stopsOnRoute && stopsOnRoute.hasOwnProperty("length") && stopsOnRoute.length > 0) {
                new Subwaymap.BusLines(stage, line, stopsOnRoute);
            }
        },

        zoomViaMouseWheel: function (e) {
            if (e?.offsetX == null)
                return false;

            var pointerPos = this.getEventPosition(e);
            var previousScaleValue = Subwaymap.scale;
            if (e.previousScaleValue != null) {
                Subwaymap.scale = e.scale;
                previousScaleValue = e.previousScaleValue;
            }
            var wheelDelta = e.originalEvent.wheelDelta;
            var detail = e.originalEvent.detail;
            if (wheelDelta && !e.isDrag) {
                if (wheelDelta > 0) {  // 放大
                    if (Subwaymap.scale <= Subwaymap.maxZoom) {
                        Subwaymap.scale += Subwaymap.sequenceZoom;
                    }
                } else {  // 缩小
                    if (Subwaymap.scale >= Subwaymap.minZoom) {
                        Subwaymap.scale -= Subwaymap.sequenceZoom;
                    }
                }
            }
            else if (detail) {  //ff的事件不同，而且向下向上滚动的值不同
                if (detail > 0) {
                    if (Subwaymap.scale <= Subwaymap.maxZoom) {
                        Subwaymap.scale += Subwaymap.sequenceZoom;
                    }
                } else {
                    if (Subwaymap.scale >= Subwaymap.minZoom) {
                        Subwaymap.scale -= Subwaymap.sequenceZoom;
                    }
                }
            }

            zoomScale = {
                offsetX: pointerPos.x,
                offsetY: pointerPos.y,
                originalEvent: {
                    wheelDelta: wheelDelta,
                    detail: 0
                },
                scale: Subwaymap.scale,
                isDrag: e.isDrag,
                previousScaleValue: previousScaleValue,
                sx: zoomScale.sx,
                sy: zoomScale.sy,
                isNewDrag: zoomScale.isNewDrag
            };

            this.zoomMap(Subwaymap.scale, previousScaleValue, pointerPos);
            zoomScale.isNewDrag = false;

            return false;
        },
        getEventPosition: function (ev) {
            var x, y;
            if (ev.offsetX || ev.offsetX == 0) {
                x = ev.offsetX;
                y = ev.offsetY;
            }
            return { x: x, y: y };
        },
        zoomMap: function (scale, oldScale, pointerPos) {
            var stagePos = this.stage.position();

            var vx = pointerPos.x - stagePos.x;
            var vy = pointerPos.y - stagePos.y;

            var ax = vx / oldScale;
            var ay = vy / oldScale;

            var sx = stagePos.x - ax * (scale - oldScale);
            var sy = stagePos.y - ay * (scale - oldScale);

            if (zoomScale.isDrag && !zoomScale.isNewDrag) {
                sx = zoomScale.sx;
                sy = zoomScale.sy;
            }
            zoomScale.sx = sx;
            zoomScale.sy = sy;

            //Subwaymap.postionX = sx;
            //Subwaymap.postionY = sy;

            this.stage.scale({ x: scale, y: scale });
            this.stage.draw();

            this.stage.position({ x: sx, y: sy });
            this.stage.draw();

        }
    }
});

